﻿using Aliyun.OSS;
using CKS.Core.Framework;
using FreeSql;
using System;
using System.Collections.Generic;
using System.Data.OleDb;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZR.Model.Models.ProductionControl;

namespace CKS.PLC.Action.Subscription
{

    public class SaveAlarmAction : PLCAction
    {
        /// <summary>
        /// 报警订阅
        /// </summary>
        /// <param name="_value"></param>
        public SaveAlarmAction(DecodeValue _value) : base(_value)
        {
        }

        public override void Execute()
        {
            /*
             和缓存值进行比较，
             有变化则做报警记录处理
             
             */
            List<ChangeValue> changes = new List<ChangeValue>();
            int wordLength = 2;
            var offset = Value.Position.BytePosition;
            if(Value.OldValue is int ) //说明是第一次比较
            {
                var vals =Value.Value.Adapt<List<int>>();
                for (int i = 0; i < vals.Count; i++)
                {
                    var position = i * wordLength + offset;
                    var wordId = position.ToInt() / wordLength;
                    changes.Add(new ChangeValue() { WordId = wordId , IsChange = true,Value = vals[i],BytePosition = position  });
                }
            }
            else
            {   //和OldValue比较
                var vals = Value.Value.Adapt<List<int>>();
                var ovals = Value.OldValue.Adapt<List<int>>();
                for (int i = 0; i < vals.Count; i++)
                {
                    var position = i * wordLength + offset;
                    var wordId = position.ToInt() / wordLength;
                    if (vals[i] != ovals[i]) //两值不相等
                        changes.Add(new ChangeValue() { WordId = wordId , IsChange = true, Value = vals[i],OldValue = ovals[i], BytePosition = position });
                }
            }

            //得出数组中真正变化的项，进行逻辑处理
            Stopwatch sw = Stopwatch.StartNew();
            foreach (var item in changes)
            {
                ProcessChange(item);
            }
            sw.Stop();
            Debug.WriteLine($"处理报警{changes.Count*16}条, 耗时：{sw.ElapsedMilliseconds}ms");

        }
        
        private void ProcessChange(ChangeValue Item)
        {
            // 1个word有16位，所以需要处理16个bit
            //按word取bool数组
            var calcoldvalue = Item.OldValue == -1? 0:Item.OldValue;
            var oldbools = ConvertWordToOrderedBoolTuples((ushort)calcoldvalue);
            var newbools = ConvertWordToOrderedBoolTuples((ushort)Item.Value);
            for (int i = 0; i < newbools.Count(); i++)
            {
                var newItem = newbools[i];
                var oldItem = oldbools[i];
                bool allowProcess = false;
                if (Item.OldValue == -1)
                {
                    allowProcess = true;
                }
                else
                {
                    if (newItem.Value != oldItem.Value)//每1位和Old值比较
                        allowProcess = true;
                }
                if (!allowProcess)
                    continue;
                var BitIndex = Item.WordId * 16 + i + 1; //因为i从0开始，所以需要加1
                var dict = conn.Select<CksAlarmDict>().Where(a => a.BitId == BitIndex).First();
                if (dict == null)
                {
                    if (newItem.Value)
                        EventBus.AddLog($"设备报警但缺少报警字典:{BitIndex} ");
                    continue;
                }
                if (newItem.Value)
                {
                    //报警了新增报警记录
                    Debug.WriteLine($"{dict.SignalAddress}报警了");
                    //查询数据库，不存在则新增
                    var records = conn.Select<CksAlarmRecord>()
                        .Where(a => a.Status == 1 && a.AlarmDictId == BitIndex)
                        .ToList();
                    if (records.Count == 0)
                    {
                        var record = new CksAlarmRecord()
                        {
                            AlarmDictId = BitIndex,
                            StartTime = DateTime.Now,
                            SignalAddress = dict.SignalAddress,
                            FaultCase = dict.FaultCase,
                            Solution = dict.Solution,
                            DeviceName = dict.DeviceName,
                            Status = 1,
                            AlarmCode = dict.AlarmCode,
                        };
                        conn.Insert(record).ExecuteAffrows();
                        EventBus.AddLog($"{record.SignalAddress} 设备报警:{record.FaultCase} 解决方法:{record.Solution}");
                    }
                }
                else
                {
                    //警报消除 

                    conn.Update<CksAlarmRecord>().Set(a => a.Status, 10)
                        .Set(a => a.EndTime, DateTime.Now)
                        .Where(a => a.Status == 1 && a.AlarmDictId == BitIndex)
                        .ExecuteAffrows();
                    if (Item.OldValue != -1)
                    {
                        EventBus.AddLog($"设备报警消除:{dict.SignalAddress} ");
                        Debug.WriteLine($"{dict.SignalAddress}消除");
                    }
                }
            }

            
        }



        public  List<(bool Value, int Index)> ConvertWordToOrderedBoolTuples(ushort word)
        {
            // 获取高低字节（西门子是大端序）
            byte highByte = (byte)(word >> 8);  // 高字节(DBB0)
            byte lowByte = (byte)(word & 0xFF); // 低字节(DBB1)

            var boolTuples = new List<(bool Value, int Index)>(16);

            // 处理高字节（对应BOOL[0]-BOOL[7] = DBX0.0-DBX0.7）
            for (int i = 0; i < 8; i++)
            {
                bool bitValue = (highByte & (1 << i)) != 0;
                boolTuples.Add((bitValue, i));
            }

            // 处理低字节（对应BOOL[8]-BOOL[15] = DBX1.0-DBX1.7）
            for (int i = 0; i < 8; i++)
            {
                bool bitValue = (lowByte & (1 << i)) != 0;
                boolTuples.Add((bitValue, i + 8));
            }

            // 按索引升序返回
            return boolTuples.OrderBy(t => t.Index).ToList();
        }



    }

    class ChangeValue
    {
        /// <summary>
        /// 唯一Id 每一位1个Id,和字典关联
        /// </summary>
        public int Id {  get; set; }
        /// <summary>
        /// word的编号 
        /// </summary>
        public int WordId { get; set; }
        public bool IsChange { get; set; }

        public int Value { get; set; }

        public int OldValue { get; set; } = -1;
        /// <summary>
        /// word占2个字节
        /// </summary>
        public int ByteLenth { get; set; } = 2;
        /// <summary>
        /// 起始位置
        /// </summary>
        public decimal BytePosition { get; set; }

        
    }

   


}
